package com.hunhjy.shiro.realm;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;

import com.hunhjy.shiro.dto.common.UserRolesDto;
import com.hunhjy.shiro.dto.common.UsersDto;
import com.hunhjy.shiro.services.UserService;
import com.hunhjy.wx.action.WechartAction;

/**
 * @Description 自定义Realm 继承自AuthorizingRealm
 * @author mawenzheng
 * @Date 2016-6-30
 */
public class WxAuthorizingRealm extends AuthorizingRealm {
	private static Logger log = LogManager.getLogger(WechartAction.class);
	@Resource
	private UserService userService;

	/**
	 * 为当前登录的Subject授予角色和权限
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		log.debug("======授予角色和权限 ===");
		String usercode = (String) principals.fromRealm(getName()).iterator().next();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("usercode", usercode);
		System.out.println("usercode::???"+usercode);
		// 根据用户名查找拥有的角色
		List<UserRolesDto> roles = userService.getUserRoles(map);
		if (roles != null) {
			log.info("=====roles.size:"+roles.size());
			SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

			for (UserRolesDto role : roles) {
				info.addRole(role.getName());
				log.info(usercode + ":角色=" + role.getName());
			}
			return info;
		}
		// 若该方法什么都不做直接返回null的话,就会导致任何用户访问/admin/listUser.jsp时都会自动跳转到unauthorizedUrl指定的地址
				// 详见applicationContext.xml中的<bean id="shiroFilter">的配置
			return null;
	}

	/**
	 * 验证当前登录的Subject
	 * 
	 * @see 经测试:本例中该方法的调用时机为LoginController.login()方法中执行Subject.login()时
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) {
		log.debug("======验证当前登录的Subject  ===");
		// 获取基于用户名和密码的令牌
		// 实际上这个authcToken是从LoginController里面currentUser.login(token)传过来的
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		System.out.println("验证当前Subject时获取到token为" + ReflectionToStringBuilder.toString(token,ToStringStyle.MULTI_LINE_STYLE));
		//获取用户名（用户代码，登陆账号）
		String usercode = String.valueOf(token.getUsername());
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("usercode", usercode);
		//根据用户代码查询是否存在当前用户
		List<UsersDto> list = userService.getUsers(map);
		if (list != null && list.size() == 1) {
			UsersDto user=list.get(0);
			//若存在当前用户，则判断密码，密码相同，则认证通过
			System.out.println(user.getPassword()+"=="+String.valueOf(token.getPassword()));
			//根据从数据库中查询出来的数据生成一个凭证
			//将从数据库中查询的密码存入了authcInfo里，前台传的密码在token里，shiro会自动校验
			AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUsercode(), user.getPassword(), this.getName());
			//存入session
			this.setSession("currentUser",user);
			//返回authcInfo则说明认证通过，返回null就是未通过认证
			return authcInfo;
		}
		// 没有返回登录用户名对应的SimpleAuthenticationInfo对象时,就会在LoginController中抛出UnknownAccountException异常
		log.error("系统中不存在此用户");
		return null;
	}

	/**
	 * 将一些数据放到ShiroSession中,以便于其它地方使用
	 * 
	 * @see 比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到
	 */
	private void setSession(Object key, Object value) {
		Subject currentUser = SecurityUtils.getSubject();
		if (null != currentUser) {
			Session session = currentUser.getSession();
			System.out.println("Session默认超时时间为[" + session.getTimeout() + "]毫秒");
			if (null != session) {
				session.setAttribute(key, value);
			}
		}
	}
}